import * as step from '@flow-step/step-toolkit'

const defaultMaxAttempts = 6
const defaultSeconds = 1

export class RetryHelper {
    private maxAttempts: number
    private sleepSeconds: number

    constructor(
        maxAttempts: number = defaultMaxAttempts,
        sleepSeconds: number = defaultSeconds
    ) {
        this.maxAttempts = maxAttempts
        this.sleepSeconds = sleepSeconds
    }

    async execute<T>(action: () => Promise<T>): Promise<T> {
        let attempt = 1
        while (attempt < this.maxAttempts) {
            try {
                return await action()
            } catch (err) {
                step.error((err as any)?.message)
            }

            // Sleep
            const seconds = this.sleepSeconds
            step.info(`Waiting ${seconds} seconds before trying again`)
            await this.sleep(seconds)
            attempt++
        }

        // Last attempt
        return await action()
    }

    private async sleep(seconds: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, seconds * 1000))
    }
}

export async function execute<T>(action: () => Promise<T>): Promise<T> {
    const retryHelper = new RetryHelper()
    return await retryHelper.execute(action)
}
